package com.bizfx.component.fields
{
	import flash.display.DisplayObject;
	import flash.events.Event;
	import flash.events.EventDispatcher;
	import flash.events.IEventDispatcher;
	
	import com.bizfx.component.views.IDetailView;
	import com.bizfx.utils.StringUtils;
	
	import mx.collections.ArrayCollection;
	import mx.collections.IList;
	import mx.containers.Box;
	import mx.controls.CheckBox;
	import mx.core.Application;
	import mx.core.IFlexDisplayObject;
	import mx.core.IMXMLObject;
	import mx.core.mx_internal;
	import mx.events.FlexEvent;
	import mx.utils.UIDUtil;
	
	use namespace mx_internal;

	[Event(name="change", type="flash.events.Event")]
	[Event(name="itemClick", type="mx.events.ItemClickEvent")]
	
	[DefaultBindingProperty(source="selection", destination="selection")]	
	[DefaultTriggerEvent("change")]
	
	public class CheckBoxGroupField extends Box implements IField
	{
		private var checkBoxes:Array /* of CheckBoxItem */ = [];
		
		private var dataDirty:Boolean = false;
		
		public function CheckBoxGroupField(document:IFlexDisplayObject = null)
		{
			super();
			this.visible = false;
			this.includeInLayout = false;
		}
		
		public function get fieldKey():String
		{
			return this.id;
		}
		
		public function set fieldKey(value:String):void
		{
			this.id = value;
		}
		
		private var _data:Object;

		[Inspectable(category="General")]
		override public function get data():Object {
			var result:IList = new ArrayCollection();
			var n:int = this.checkBoxes.length;
			for (var i:int = 0; i < n; i++) {
				var cb:CheckBoxItem = this.getCheckBoxAt(i);
				if (cb != null && cb.selected) {
					if (StringUtils.isNullOrEmpty(cb.value)) {
						result.addItem(cb.label);
					} else {
						result.addItem(cb.value);
					}
				}
			}
			
			return result;
		}
		
		override public function set data(value:Object):void {
			var n:int = this.checkBoxes.length;
			var i:int = 0;
			var cb:CheckBoxItem;
			if (value == null) {
				for (i = 0; i < n; i++) {
					cb = this.getCheckBoxAt(i);
					if (cb != null) {
						cb.selected = false;
					}
				}
			}
			if (value is IList) {
				for (i = 0; i < n; i++) {
					cb = this.getCheckBoxAt(i);
					if (cb != null) {
						var cbv:String = StringUtils.isNullOrEmpty(cb.value)? cb.label: cb.value;
						cb.selected = IList(value).getItemIndex(cbv) >= 0;
					}
				}
			}
		}
		
		[Inspectable(category="General", enumeration="true,false", defaultValue="false")]
		[Bindable("readOnlyChanged")]
		public function get readOnly():Boolean {
			return this.enabled;
		}
		
		public function set readOnly(value:Boolean):void {
			if (this.enabled == value) {
				this.enabled = !value;
				this.dispatchEvent(new Event("readOnlyChanged"));
			}
		}
		
		private var _bindProperty:String;
		[Bindable("bindPropertyChange")]
		public function get bindProperty():String
		{
			return _bindProperty;
		}
		
		public function set bindProperty(value:String):void {
			if (this._bindProperty != value) {
				_bindProperty = value;
				this.dispatchEvent(new Event("bindPropertyChange"));
			}
		}
		
		[Bindable("enabledChange")]
		[Inspectable(category="General", defaultValue="true")]
		override public function get enabled():Boolean
		{
			var s:Number = 0;
			
			var n:int = checkBoxes.length;
			for (var i:int = 0; i < n; i++)
			{
				s = s + getCheckBoxAt(i).enabled;
			}
			
			if (s == 0)
				return false;
			
			if (s == n)
				return true;
			
			return false;
		}
		
		override public function set enabled(value:Boolean):void
		{
			var n:int = checkBoxes.length;
			for (var i:int = 0; i < n; i++)
			{
				this.getCheckBoxAt(i).enabled = value;
			}
			
			this.dispatchEvent(new Event("enabledChange"));
		}
		
		private var _labelPlacement:String = "right";
		
		[Bindable("labelPlacementChanged")]
		[Inspectable(category="General", enumeration="left,right,top,bottom", defaultValue="right")]
		public function get labelPlacement():String
		{
			return _labelPlacement;
		}
		
		public function set labelPlacement(value:String):void
		{
			_labelPlacement = value;
			
			var n:int = checkBoxes.length;
			for (var i:int = 0; i < n; i++)
			{
				getCheckBoxAt(i).labelPlacement = value;
			}
		}

//		private var _view:IDetailView;
//		
//		public function get view():IDetailView
//		{
//			return this._view;
//		}
//		
//		public function set view(value:IDetailView):void {
//			if (StringUtils.isNullOrEmpty(this.id)) {
//				this.id = UIDUtil.createUID();
//			}
//			if (this._view !== value) {
//				if (_view) {
//					_view.removeFieldByKey(this.fieldKey);
//				}
//				this._view = value;
//				if (_view) {
//					_view.addField(this);
//				}
//			}
//		}
			
		public function getCheckBoxAt(index:int):CheckBoxItem
		{
			return CheckBoxItem(checkBoxes[index]);
		}
		
		mx_internal function addInstance(instance:CheckBoxItem):void
		{
			instance.addEventListener(Event.REMOVED, checkBox_removedHandler);    
			checkBoxes.push(instance);
			
			dispatchEvent(new Event("numCheckBoxesChanged"));
		}
		
		mx_internal function removeInstance(instance:CheckBoxItem):void
		{
			if (instance)
			{
				var foundInstance:Boolean = false;
				for (var i:int = 0; i < checkBoxes.length; i++)
				{
					var cb:CheckBoxItem = getCheckBoxAt(i);

					if (!foundInstance && cb == instance)
					{
						cb.group = null;
						// Remove the radio button from the internal array
						checkBoxes.splice(i,1); 
						foundInstance = true;
						// redo the same index because we removed the previous item at this index
						i--; 
					}
				}  
				
				if (foundInstance)
					dispatchEvent(new Event("numCheckBoxesChanged"));
			}
		}
		
		private function checkBox_removedHandler(event:Event):void
		{
			var rb:CheckBoxItem = event.target as CheckBoxItem;
			if (rb)
			{
				rb.removeEventListener(Event.REMOVED, checkBox_removedHandler);
				removeInstance(CheckBoxItem(event.target));
			}
		}
	}
}